home *** CD-ROM | disk | FTP | other *** search
/ Turnbull China Bikeride / Turnbull China Bikeride - Disc 2.iso / STUTTGART / TEX-UTIL / DVIPS_55 / dvips / src / c / output < prev    next >
Text File  |  1994-05-06  |  35KB  |  1,300 lines

  1. /*
  2.  *   These routines do most of the communicating with the printer.
  3.  *
  4.  *   LINELENGTH tells the maximum line length to send out.  It's been
  5.  *   reduced to 72 because sometimes PostScript files are included in
  6.  *   mail messages and many mailers mutilate longer lines.
  7.  */
  8. #define LINELENGTH (72)
  9. #include "dvips.h" /* The copyright notice in that file is included too! */
  10. #include <ctype.h>
  11.  
  12. #ifdef OS2
  13. #include <stdlib.h>
  14. #ifdef _MSC_VER
  15. #define popen(pcmd, pmode)  _popen(pcmd, pmode)
  16. #define pclose(pstream) _pclose(pstream)
  17. #endif
  18. #endif
  19. /*
  20.  *   The external routines called here:
  21.  */
  22. extern void error() ;
  23. extern void send_headers() ;
  24. extern int add_header() ;
  25. extern FILE *search() ;
  26. extern char *getenv() ;
  27. extern void makepsname() ;
  28. extern void handlepapersize() ;
  29. extern void findbb() ;
  30. /*
  31.  *   These are the external variables used by these routines.
  32.  */
  33. extern integer hh, vv ;
  34. extern fontdesctype *curfnt ;
  35. extern FILE *bitfile ;
  36. extern char *oname ;
  37. extern Boolean secure ;
  38. extern Boolean reverse ;
  39. extern Boolean removecomments ;
  40. extern Boolean sendcontrolD, disablecomments, multiplesects ;
  41. extern Boolean usesPSfonts, headers_off ;
  42. extern Boolean safetyenclose ;
  43. extern Boolean cropmarks ;
  44. extern Boolean tryepsf ;
  45. extern Boolean compressed ;
  46. extern int numcopies ;
  47. extern int collatedcopies ;
  48. extern integer pagecopies ;
  49. extern int totalpages ;
  50. extern integer pagenum ;
  51. extern Boolean manualfeed ;
  52. extern int landscape ;
  53. extern int quiet ;
  54. extern int prettycolumn ;
  55. extern int actualdpi, vactualdpi ;
  56. extern char *iname, *nextstring ;
  57. extern char *paperfmt ;
  58. /* extern char *headerpath ; */
  59. extern char errbuf[] ;
  60. extern shalfword linepos ;
  61. /* extern char *figpath ; */
  62. extern struct header_list *ps_fonts_used ;
  63. extern char banner[] ;
  64. extern int gargc ;
  65. extern char **gargv ;
  66. extern struct papsiz *papsizes ;
  67. extern integer hpapersize, vpapersize ;
  68. char preamblecomment[256] ; /* usually "TeX output ..." */
  69. /*
  70.  *   We need a few statics to take care of things.
  71.  */
  72. static integer rhh, rvv ;
  73. static int instring ;
  74. static Boolean lastspecial = 1 ;
  75. static shalfword d ;
  76. static Boolean popened = 0 ;
  77. int lastfont ; /* exported to dospecial to fix rotate.tex problem */
  78. static void chrcmd();                   /* just a forward declaration */
  79. static char strbuffer[LINELENGTH + 20], *strbp = strbuffer ;
  80. static struct papsiz *finpapsiz ;
  81. static struct papsiz defpapsiz = {
  82.    0, 40258437L, 52099154L, "letter", ""
  83. } ;
  84. #ifdef CREATIONDATE
  85. #if !defined(VMS) && !defined(ARCH) && !defined(MSDOS) && !(defined(OS2) && defined(_MSC_VER))
  86.  /* VAXC/MSDOS don't like/need this !! */
  87. #include <sys/types.h>
  88. #include <sys/time.h> /* time(), at least on BSD Unix */
  89. #endif
  90. #include <time.h> /* asctime() and localtime(), at least on BSD Unix */
  91. static time_t jobtime;
  92. #endif
  93. /*
  94.  *   This routine copies a file down the pipe.  Search path uses the
  95.  *   header path.
  96.  *
  97.  *   We add code to handle the case of MS-DOS font files.
  98.  *
  99.  *   Format:  80 {01,02} four byte length in littleendian order data
  100.  *   repeated possibly multiple times.
  101.  */
  102. static char *hxdata = "0123456789ABCDEF" ;
  103. static int infigure ;
  104. extern char *infont ;
  105. static char *begbinary = "\n%%BeginBinary:" ;
  106. void
  107. copyfile(s)
  108.         char *s ;
  109. {
  110.    FILE *f = NULL ;
  111.    int c, prevc = '\n' ;
  112.    long len ;
  113.    char *bbmatch = begbinary ;
  114.    /* begin DOS EPS code */
  115.    int doseps = 0;
  116.    unsigned long dosepsbegin, dosepsend;
  117.    /* end DOS EPS code */
  118. #ifdef VMCMS
  119.    register char *lastdirsep ;
  120.    register char *trunc_s ;
  121.    trunc_s = s ;
  122. #endif
  123. #ifdef MVSXA
  124.    register char *lastdirsep ;
  125.    register char *trunc_s ;
  126.    trunc_s = s ;
  127. #endif
  128.  
  129.    switch (infigure) {
  130.    case 1:
  131. /*
  132.  *   Look in headerpath too, just in case.  This allows common header
  133.  *   or figure files to be installed in the .../ps directory.
  134.  */
  135.       f = search(figpath, s, READ) ;
  136.       if (f == 0)
  137.          f = search(headerpath, s, READ) ;
  138. #ifdef VMCMS
  139.       lastdirsep = strrchr(s, '/') ;
  140.       if ( NULL != lastdirsep ) trunc_s = lastdirsep + 1 ;
  141.       (void)sprintf(errbuf,
  142.    "Couldn't find figure file %s with CMS name %s; continuing", s, trunc_s) ;
  143. #else
  144. #ifdef MVSXA
  145.       lastdirsep = strrchr(s, '/') ;
  146.       if ( NULL != lastdirsep ) trunc_s = lastdirsep + 1 ;
  147.       (void)sprintf(errbuf,
  148.     "Couldn't find figure file %s with MVS name %s; continuing", s, trunc_s) ;
  149. #else
  150.       (void)sprintf(errbuf, "Couldn't find figure file %s; continuing", s) ;
  151. #endif
  152. #endif
  153.       break ;
  154.    default:
  155.       f = search(headerpath, s, READ) ;
  156.       (void)sprintf(errbuf, "! Couldn't find header file %s", s) ;
  157.       break ;
  158. #ifndef VMCMS
  159. #ifndef MVSXA
  160. #ifndef VMS
  161. #ifndef MSDOS
  162. #ifndef __THINK__
  163.    case 2:
  164. #ifdef SECURE
  165.       (void)sprintf(errbuf, "<%s>: Tick filename execution disabled", s) ;
  166. #else
  167. #ifdef OS2
  168.       if (_osmode == OS2_MODE) {
  169. #endif
  170.       if (secure == 0)
  171.          f = popen(s, "r") ;
  172. #ifdef OS2
  173.       }
  174. #endif
  175.       (void)sprintf(errbuf, "Failure to execute %s; continuing", s) ;
  176. #endif
  177.       break;
  178. #endif
  179. #endif
  180. #endif
  181. #endif
  182. #endif
  183.    }
  184.    if (f==NULL)
  185.       error(errbuf) ;
  186.    else {
  187.       if (! quiet) {
  188.          if (strlen(s) + prettycolumn > STDOUTSIZE) {
  189.             fprintf(stderr, "\n") ;
  190.             prettycolumn = 0 ;
  191.          }
  192. #ifdef VMCMS
  193.          (void)fprintf(stderr, "<%s>", trunc_s) ;
  194. #else
  195. #ifdef MVSXA
  196.          (void)fprintf(stderr, "<%s>", trunc_s) ;
  197. #else
  198.          (void)fprintf(stderr, "<%s>", s) ;
  199. #endif
  200. #endif
  201.          (void)fflush(stderr) ;
  202.          prettycolumn += 2 + strlen(s) ;
  203.       }
  204.       if (linepos != 0)
  205.          (void)putc('\n', bitfile) ;
  206.       if (! disablecomments)
  207.          if (infigure)
  208.             (void)fprintf(bitfile, "%%%%BeginDocument: %s\n", s) ;
  209.          else if (infont)
  210.             (void)fprintf(bitfile, "%%%%BeginFont: %s\n", infont) ;
  211.          else
  212.             (void)fprintf(bitfile, "%%%%BeginProcSet: %s\n", s) ;
  213.       c = getc(f) ;
  214.       if (c == 0x80) {
  215. #if defined MSDOS || defined OS2
  216.          (void)fclose(f) ;  /* close MSDOS font file */
  217.          f = search(headerpath, s, READBIN) ;  /* reopen in BINARY mode */
  218.          (void)sprintf(errbuf, "! Couldn't find header file %s", s) ;
  219.          if (f==NULL)
  220.            error(errbuf) ;
  221.          c = getc(f);
  222. #endif
  223.          while (1) {
  224.             c = getc(f) ;
  225.             switch(c) {
  226. case 1:
  227. case 2:
  228.                len = getc(f) ;
  229.                len += getc(f) * 256L ;
  230.                len += getc(f) * 65536L ;
  231.                len += getc(f) * 256L * 65536 ;
  232.                if (c == 1) {
  233.                   while (len > 0) {
  234.                      c = getc(f) ;
  235.                      if (c == EOF) {
  236.                         error("premature EOF in MS-DOS font file") ;
  237.                         len = 0 ;
  238.                      } else {
  239.                         if (c == 13)
  240.                            (void)putc('\n', bitfile) ;
  241.                         else
  242.                            (void)putc(c, bitfile) ;
  243.                         len-- ;
  244.                      }
  245.                   }
  246.                } else {
  247.                   putc('\n', bitfile) ;
  248.                   prevc = 0 ;
  249.                   while (len > 0) {
  250.                      c = getc(f) ;
  251.                      if (c == EOF) {
  252.                         error("premature EOF in MS-DOS font file") ;
  253.                         len = 0 ;
  254.                      } else {
  255.                         (void)putc(hxdata[c >> 4], bitfile) ;
  256.                         (void)putc(hxdata[c & 15], bitfile) ;
  257.                         len-- ;
  258.                         prevc += 2 ;
  259.                         if (prevc >= 76) {
  260.                            putc('\n', bitfile) ;
  261.                            prevc = 0 ;
  262.                         }
  263.                      }
  264.                   }
  265.                }
  266.                break ;
  267. case 3:
  268.                goto msdosdone ;
  269. default:
  270.                error("saw type other than 1, 2, or 3 in MS-DOS font file") ;
  271.                break ;
  272.             }
  273.             c = getc(f) ;
  274.             if (c == EOF)
  275.                break ;
  276.             if (c != 0x80) {
  277.                error("saw non-MSDOS header in MSDOS font file") ;
  278.                break ;
  279.             }
  280.          }
  281. msdosdone:
  282.          prevc = 0 ;
  283.       } else {
  284. /* begin DOS EPS code */
  285.          if (c == 'E'+0x80) {
  286.             if ((getc(f)=='P'+0x80) && (getc(f)=='S'+0x80)
  287.                                 && (getc(f)=='F'+0x80)) {
  288. #if defined MSDOS || defined OS2
  289.                (void)fclose(f) ;  /* close DOS EPS file */
  290.                f = search(headerpath, s, READBIN) ;
  291.                                                    /* reopen in BINARY mode */
  292.                (void)sprintf(errbuf, "! Couldn't find header file %s", s) ;
  293.                if (f==NULL)
  294.                  error(errbuf) ;
  295.                fseek(f, 4L, 0);
  296. #endif
  297.                doseps = 1;
  298.                dosepsbegin = getc(f) ;
  299.                dosepsbegin += getc(f) * 256L ;
  300.                dosepsbegin += getc(f) * 65536L ;
  301.                dosepsbegin += getc(f) * 256L * 65536 ;
  302.                dosepsend = getc(f) ;
  303.                dosepsend += getc(f) * 256L ;
  304.                dosepsend += getc(f) * 65536L ;
  305.                dosepsend += getc(f) * 256L * 65536 ;
  306.                dosepsend += dosepsbegin;
  307. #if defined MSDOS || defined OS2
  308.                (void)fclose(f) ;  /* close DOS EPS file */
  309.                f = search(headerpath, s, READ) ;  /* reopen in TEXT mode */
  310.                (void)sprintf(errbuf, "! Couldn't find header file %s", s) ;
  311.                if (f==NULL)
  312.                  error(errbuf) ;
  313. #endif
  314.                fseek(f, dosepsbegin, 0);
  315.                c = getc(f);
  316.             }
  317.             else {
  318.                rewind(f);
  319.                c = getc(f);
  320.             }
  321.          }
  322. /* end DOS EPS code */
  323.          if (c != EOF) {
  324.             while (1) {
  325.                if (c == *bbmatch) {
  326.                   bbmatch++ ;
  327.                   if (*bbmatch == '\0') {
  328.                      integer size = 0 ;
  329.  
  330.                      if (removecomments)
  331.                         (void)fputs(begbinary, bitfile) ;
  332.                      (void)putc(c, bitfile) ;
  333.                      while (1) {
  334.                         c = getc(f) ;
  335.                         if (c == ' ')
  336.                            (void)putc(c, bitfile) ;
  337.                         else
  338.                            break ;
  339.                      }
  340.                      while ('0' <= c && c <= '9') {
  341.                         size = size * 10 + c - '0' ;
  342.                         (void)putc(c, bitfile) ;
  343.                         c = getc(f) ;
  344.                      }
  345.                      while (c != '\r' && c != '\n') {
  346.                         if (c == EOF)
  347.                            error("! bad BeginBinary line in epsf") ;
  348.                         (void)putc(c, bitfile) ;
  349.                         c = getc(f) ;
  350.                      }
  351.                      (void)putc(c, bitfile) ;
  352.                      for (; size>0; size--) {
  353.                         c = getc(f) ;
  354.                         if (c == EOF)
  355.                            error("! premature end of file in binary section") ;
  356.                         (void)putc(c, bitfile) ;
  357.                      }
  358.                      c = getc(f) ;
  359.                      if (c == '\n' || c == '\r') {
  360.                         (void)putc(c, bitfile) ;
  361.                         c = getc(f) ;
  362.                      }
  363.                      if (c != '%')
  364.                         error("! expected to see %%EndBinary at end of data") ;
  365.                      while (1) {
  366.                         (void)putc(c, bitfile) ;
  367.                         if (c == '\r' || c == '\n')
  368.                            break ;
  369.                         c = getc(f) ;
  370.                         if (c == EOF)
  371.                            error("! premature end of file in binary section") ;
  372.                      }
  373.                      c = getc(f) ;
  374.                   }
  375.                } else
  376.                   bbmatch = begbinary ;
  377.                if (removecomments && c == '%' && prevc == '\n') {
  378.                          /* skip comments */
  379.                  /* revised:  only skip %% and %! comments */
  380.                   c = getc(f) ;
  381.                   if (c == '%' || c == '!') {
  382.                      while ((c=getc(f))!=EOF) {
  383.                         if (c == '\n' || c == '\r') {
  384.                            c = '\n' ;
  385.                            break ;
  386.                         }
  387.                      }
  388.           } else {
  389.              (void)putc('%', bitfile) ;
  390.              if (c != EOF)
  391.                         (void)putc(c, bitfile) ;
  392.           }
  393. #ifdef VMCMS
  394.                } else if (c != 0x37 ) {
  395. #else
  396. #ifdef MVSXA
  397.                } else if (c != 0x37 ) {
  398. #else
  399.                } else if (c != 4) {
  400. #endif
  401. #endif
  402.                   (void)putc(c, bitfile) ;
  403.                }
  404.                prevc = c ;
  405. /* begin DOS EPS code */
  406.                if (doseps && (ftell(f)>=dosepsend))
  407.                   break;      /* stop at end of DOS EPS PostScript section */
  408. /* end DOS EPS code */
  409.                c = getc(f) ;
  410.                if (c == EOF)
  411.                   break ;
  412.                else if (c == '\r')
  413.                   c = '\n' ;
  414.             }
  415.          }
  416.       }
  417.       if (prevc != '\n')
  418.          (void)putc('\n', bitfile) ;
  419.       linepos = 0 ;
  420. #ifndef VMCMS
  421. #ifndef MVSXA
  422. #ifndef VMS
  423. #ifndef MSDOS
  424. #ifndef __THINK__
  425.       if (infigure == 2)
  426. #ifdef OS2
  427.          {
  428.             if (_osmode == OS2_MODE)
  429.                (void)pclose(f) ;
  430.          }
  431. #else
  432.          (void)pclose(f) ;
  433. #endif
  434.       else
  435. #endif
  436. #endif
  437. #endif
  438. #endif
  439. #endif
  440.          (void)fclose(f) ;
  441.       if (!disablecomments)
  442.          if (infigure)
  443.             (void)fprintf(bitfile, "%%%%EndDocument\n") ;
  444.          else if (infont)
  445.             (void)fprintf(bitfile, "%%%%EndFont\n") ;
  446.          else
  447.             (void)fprintf(bitfile, "%%%%EndProcSet\n") ;
  448.    }
  449. }
  450.  
  451. /*
  452.  *   For included PostScript graphics, we use the above routine, but
  453.  *   with no fatal error message.
  454.  */
  455. void figcopyfile(s, systemtype)
  456. char *s ;
  457. int systemtype ;
  458. {
  459.    infigure = systemtype ? 2 : 1 ;
  460.    copyfile(s) ;
  461.    infigure = 0 ;
  462. }
  463. /*
  464.  *   This next routine writes out a `special' character.  In this case,
  465.  *   we simply put it out, since any special character terminates the
  466.  *   preceding token.
  467.  */
  468. void
  469. specialout(c)
  470.         char c ;
  471. {
  472.    if (linepos >= LINELENGTH) {
  473.       (void)putc('\n', bitfile) ;
  474.       linepos = 0 ;
  475.    }
  476.    (void)putc(c, bitfile) ;
  477.    linepos++ ;
  478.    lastspecial = 1 ;
  479. }
  480.  
  481. void
  482. stringend()
  483. {
  484.    if (linepos + instring >= LINELENGTH - 2) {
  485.       (void)putc('\n', bitfile) ;
  486.       linepos = 0 ;
  487.    }
  488.    (void)putc('(', bitfile) ;
  489.    *strbp = 0 ;
  490.    (void)fputs(strbuffer, bitfile) ;
  491.    (void)putc(')', bitfile) ;
  492.    linepos += instring + 2 ;
  493.    lastspecial = 1 ;
  494.    instring = 0 ;
  495.    strbp = strbuffer ;
  496. }
  497.  
  498. void
  499. scout(c)   /* string character out */
  500.         char c ;
  501. {
  502. /*
  503.  *   Is there room in the buffer?  LINELENGTH-6 is used because we
  504.  *   need room for (, ), and a possible four-byte string \000, for
  505.  *   instance.  If it is too long, we send out the string.
  506.  */
  507.    if (instring > LINELENGTH-6) {
  508.       stringend() ;
  509.       chrcmd('p') ;
  510.    }
  511. /*  changed next line to hex representation for VMCMS port
  512.    if (c<' ' || c > 126 || c=='%' ) {
  513. */
  514.    if ( c<0x20 || c>= 0x7F || c==0x25 ) {
  515.       *strbp++ = '\\' ;
  516.       *strbp++ = '0' + ((c >> 6) & 3) ;
  517.       *strbp++ = '0' + ((c >> 3) & 7) ;
  518.       *strbp++ = '0' + (c & 7) ;
  519.       instring += 4 ;
  520.    } else {
  521. #ifdef VMCMS
  522.      c = ascii2ebcdic[c];
  523. #else
  524. #ifdef MVSXA
  525.      c = ascii2ebcdic[c];
  526. #endif
  527. #endif
  528.      if (c == '(' || c == ')' || c == '\\') {
  529.        *strbp++ = '\\' ;
  530.        *strbp++ = c ;
  531.        instring += 2 ;
  532.      } else {
  533.        *strbp++ = c ;
  534.        instring++ ;
  535.      }
  536.    }
  537. }
  538.  
  539. void
  540. cmdout(s)
  541.         char *s ;
  542. {
  543.    int l ;
  544.  
  545.    /* hack added by dorab */
  546.    if (instring) {
  547.         stringend();
  548.         chrcmd('p');
  549.    }
  550.    l = strlen(s) ;
  551.    if ((! lastspecial && linepos >= LINELENGTH - 20) ||
  552.            linepos + l >= LINELENGTH) {
  553.       (void)putc('\n', bitfile) ;
  554.       linepos = 0 ;
  555.       lastspecial = 1 ;
  556.    } else if (! lastspecial) {
  557.       (void)putc(' ', bitfile) ;
  558.       linepos++ ;
  559.    }
  560.    (void)fputs(s, bitfile) ;
  561.    linepos += l ;
  562.    lastspecial = 0 ;
  563. }
  564.  
  565.  
  566. static void
  567. chrcmd(c)
  568.         char c ;
  569. {
  570.    if ((! lastspecial && linepos >= LINELENGTH - 20) ||
  571.        linepos + 2 > LINELENGTH) {
  572.       (void)putc('\n', bitfile) ;
  573.       linepos = 0 ;
  574.       lastspecial = 1 ;
  575.    } else if (! lastspecial) {
  576.       (void)putc(' ', bitfile) ;
  577.       linepos++ ;
  578.    }
  579.    (void)putc(c, bitfile) ;
  580.    linepos++ ;
  581.    lastspecial = 0 ;
  582. }
  583.  
  584. void
  585. floatout(n)
  586.         float n ;
  587. {
  588.    char buf[20] ;
  589.  
  590.    (void)sprintf(buf, "%.2f", n) ;
  591.    cmdout(buf) ;
  592. }
  593.  
  594. void
  595. numout(n)
  596.         integer n ;
  597. {
  598.    char buf[10] ;
  599.  
  600. #ifdef SHORTINT
  601.    (void)sprintf(buf, "%ld", n) ;
  602. #else
  603.    (void)sprintf(buf, "%d", n) ;
  604. #endif
  605.    cmdout(buf) ;
  606. }
  607.  
  608. void
  609. mhexout(p, len)
  610. register unsigned char *p ;
  611. register long len ;
  612. {
  613.    register char *hexchar = hxdata ;
  614.    register int n, k ;
  615.  
  616.    while (len > 0) {
  617.       if (linepos > LINELENGTH - 2) {
  618.          (void)putc('\n', bitfile) ;
  619.          linepos = 0 ;
  620.       }
  621.       k = (LINELENGTH - linepos) >> 1 ;
  622.       if (k > len)
  623.          k = len ;
  624.       len -= k ;
  625.       linepos += (k << 1) ;
  626.       while (k--) {
  627.          n = *p++ ;
  628.          (void)putc(hexchar[n >> 4], bitfile) ;
  629.          (void)putc(hexchar[n & 15], bitfile) ;
  630.       }
  631.    }
  632. }
  633.  
  634. void
  635. fontout(n)
  636.         int n ;
  637. {
  638.    char buf[6] ;
  639.  
  640.    if (instring) {
  641.       stringend() ;
  642.       chrcmd('p') ;
  643.    }
  644.    makepsname(buf, n) ;
  645.    cmdout(buf) ;
  646. }
  647.  
  648. void
  649. hvpos()
  650. {
  651.    if (rvv != vv) {
  652.       if (instring) {
  653.          stringend() ;
  654.          numout(hh) ;
  655.          numout(vv) ;
  656.          chrcmd('y') ;
  657.       } else if (rhh != hh) {
  658.          numout(hh) ;
  659.          numout(vv) ;
  660.          chrcmd('a') ;
  661.       } else { /* hard to get this case, but it's there when you need it! */
  662.          numout(vv - rvv) ;
  663.          chrcmd('x') ;
  664.       }
  665.       rvv = vv ;
  666.    } else if (rhh != hh) {
  667.       if (instring) {
  668.          stringend() ;
  669.          if (hh - rhh < 5 && rhh - hh < 5) {
  670. #ifdef VMCMS /*  should replace 'p' in non-VMCMS line as well */
  671.             chrcmd(ascii2ebcdic[(char)(112 + hh - rhh)]) ;
  672. #else
  673. #ifdef MVSXA /*  should replace 'p' in non-MVSXA line as well */
  674.             chrcmd(ascii2ebcdic[(char)(112 + hh - rhh)]) ;
  675. #else
  676.             chrcmd((char)('p' + hh - rhh)) ;
  677. #endif
  678. #endif
  679.          } else if (hh - rhh < d + 5 && rhh - hh < 5 - d) {
  680. #ifdef VMCMS /* should replace 'g' in non-VMCMS line as well  */
  681.             chrcmd(ascii2ebcdic[(char)(103 + hh - rhh - d)]) ;
  682. #else
  683. #ifdef MVSXA /* should replace 'g' in non-MVSXA line as well  */
  684.             chrcmd(ascii2ebcdic[(char)(103 + hh - rhh - d)]) ;
  685. #else
  686.             chrcmd((char)('g' + hh - rhh - d)) ;
  687. #endif
  688. #endif
  689.             d = hh - rhh ;
  690.          } else {
  691.             numout(hh - rhh) ;
  692.             chrcmd('b') ;
  693.             d = hh - rhh ;
  694.          }
  695.       } else {
  696.          numout(hh - rhh) ;
  697.          chrcmd('w') ;
  698.       }
  699.    }
  700.    rhh = hh ;
  701. }
  702.  
  703. /*
  704.  *   initprinter opens the bitfile and writes the initialization sequence
  705.  *   to it.
  706.  */
  707. void newline()
  708. {
  709.    if (linepos != 0) {
  710.       (void)fprintf(bitfile, "\n") ;
  711.       linepos = 0 ;
  712.    }
  713.    lastspecial = 1 ;
  714. }
  715.  
  716. void
  717. nlcmdout(s)
  718.         char *s ;
  719. {
  720.    newline() ;
  721.    cmdout(s) ;
  722.    newline() ;
  723. }
  724. /*
  725.  *   Is the dimension close enough for a match?  We use a quarter inch
  726.  *   as a match; this is 65536*72.27/4 or 1,184,072 scaled points.
  727.  */
  728. static int indelta(i)
  729. integer i ;
  730. {
  731.    if (i < 0)
  732.       i = -i ;
  733.    return (i <= 1184072) ;
  734. }
  735. /*
  736.  *   A case-irrelevant string compare.
  737.  */
  738. int mlower(c)
  739. int c ;
  740. {
  741.    if ('A' <= c && c <= 'Z')
  742.       return c - 'A' + 'a' ;
  743.    else
  744.       return c ;
  745. }
  746. int ncstrcmp(a, b)
  747. char *a, *b ;
  748. {
  749.    while (*a && (*a == *b ||
  750.                        mlower(*a) == mlower(*b)))
  751.       a++, b++ ;
  752.    if (*a == 0 && *b == 0)
  753.       return 0 ;
  754.    else
  755.       return 1 ;
  756. }
  757. /*
  758.  *   Find the paper size.
  759.  */
  760. void findpapersize() {
  761.    if (finpapsiz == 0) {
  762.       struct papsiz *ps ;
  763.  
  764.       if (tryepsf && !landscape) {
  765.          finpapsiz = &defpapsiz ;
  766.          hpapersize = defpapsiz.xsize ;
  767.          vpapersize = defpapsiz.ysize ;
  768.          return ;
  769.       }
  770.       if (cropmarks) {
  771. /*
  772.  *   If user wanted crop marks, we increase the size of the page by
  773.  *   a half inch all around.
  774.  */
  775.          if (hpapersize == 0 || vpapersize == 0) {
  776.             error(
  777.  "warning: -k crop marks wanted, but no paper size specified; using default") ;
  778.             if (landscape) {
  779.                hpapersize = defpapsiz.ysize ;
  780.                vpapersize = defpapsiz.xsize ;
  781.             } else {
  782.                hpapersize = defpapsiz.xsize ;
  783.                vpapersize = defpapsiz.ysize ;
  784.             }
  785.          }
  786.          hpapersize += 2368143L ;
  787.          vpapersize += 2368143L ;
  788.          add_header(CROPHEADER) ;
  789.       }
  790.       if (paperfmt && *paperfmt) {
  791.          for (ps = papsizes; ps; ps = ps->next)
  792.             if (ncstrcmp(paperfmt, ps->name)==0)
  793.                finpapsiz = ps ;
  794.          if (finpapsiz == 0)
  795.             error("no match for papersize") ;
  796.       }
  797.       if (finpapsiz == 0 && hpapersize > 0 && vpapersize > 0) {
  798.          for (ps=papsizes; ps; ps = ps->next) {
  799.             if (indelta(ps->xsize-hpapersize) &&
  800.                 indelta(ps->ysize-vpapersize)) {
  801.                landscape = 0 ;
  802.                break ;
  803.             }
  804.          }
  805.          if (ps == 0) {
  806.             for (ps=papsizes; ps; ps = ps->next) {
  807.                if (indelta(ps->ysize-hpapersize) &&
  808.                    indelta(ps->xsize-vpapersize)) {
  809.                   landscape = 1 ;
  810.                   break ;
  811.                }
  812.             }
  813.             if (ps == 0) {
  814.                for (ps=papsizes; ps; ps = ps->next) {
  815.                   if (ps->ysize == 0 && ps->xsize == 0)
  816.                      break ;
  817.                }
  818.                if (ps == 0) {
  819.                   landscape = (hpapersize > vpapersize) ;
  820.                   error(
  821.                     "no match for special paper size found; using default") ;
  822.                }
  823.             }
  824.          }
  825.          finpapsiz = ps ;
  826.       }
  827.       if (finpapsiz == 0) {
  828.          if (papsizes)
  829.             finpapsiz = papsizes ;
  830.          else
  831.             finpapsiz = &defpapsiz ;
  832. /*
  833.  *   But change xsize/ysize to match so bounding box works.
  834.  */
  835.          if (hpapersize && vpapersize) {
  836.             if (landscape) {
  837.                finpapsiz->ysize = hpapersize ;
  838.                finpapsiz->xsize = vpapersize ;
  839.             } else {
  840.                finpapsiz->xsize = hpapersize ;
  841.                finpapsiz->ysize = vpapersize ;
  842.             }
  843.          }
  844.       }
  845. /*
  846.  *   Here, there was no papersize special.  We set the paper size from
  847.  *   the selected paper format.  If the selected paper format has no
  848.  *   sizes, we use the defaults.
  849.  */
  850.       if (hpapersize == 0 || vpapersize == 0) {
  851.          if (finpapsiz->xsize == 0 || finpapsiz->ysize == 0) {
  852.             finpapsiz->xsize = defpapsiz.xsize ;
  853.             finpapsiz->ysize = defpapsiz.ysize ;
  854.          }
  855.          if (landscape) {
  856.             vpapersize = finpapsiz->xsize ;
  857.             hpapersize = finpapsiz->ysize ;
  858.          } else {
  859.             hpapersize = finpapsiz->xsize ;
  860.             vpapersize = finpapsiz->ysize ;
  861.          }
  862. /*
  863.  *   Here, there was a papersize special, but the selected paper
  864.  *   format has 0 0 for sizes.  We set the sizes here so that the
  865.  *   bounding box works.
  866.  */
  867.       } else if (finpapsiz->xsize == 0 || finpapsiz->ysize == 0) {
  868.          finpapsiz->xsize = hpapersize ;
  869.          finpapsiz->ysize = vpapersize ;
  870. /*
  871.  *   Here, the user specified a size with -t, and there was a
  872.  *   papersize special, and its sizes were greater than zero.
  873.  *   We make sure the sizes are okay.  Note that the user must have
  874.  *   specified landscape if this is desired.
  875.  */
  876.       } else if (paperfmt && *paperfmt) {
  877.          if (landscape) {
  878.             if (!indelta(vpapersize - finpapsiz->xsize) ||
  879.                 !indelta(hpapersize - finpapsiz->ysize)) {
  880.                if (vpapersize > finpapsiz->xsize ||
  881.                    hpapersize > finpapsiz->ysize)
  882.                   error("warning: -t selected paper may be too small") ;
  883.                else
  884.                   error("note: -t selected paper may be too large") ;
  885.             }
  886.          } else {
  887.             if (!indelta(hpapersize - finpapsiz->xsize) ||
  888.                 !indelta(vpapersize - finpapsiz->ysize)) {
  889.                if (hpapersize > finpapsiz->xsize ||
  890.                    vpapersize > finpapsiz->ysize)
  891.                   error("warning: -t selected paper may be too small") ;
  892.                else
  893.                   error("note: -t selected paper may be too large") ;
  894.             }
  895.          }
  896.       }
  897.    }
  898. }
  899. /*
  900.  *   Convert scaled points to PostScript points.  This is the same
  901.  *   as return (i * 72 / (65536 * 72.27)), which is the same as
  902.  *   dividing by 65781.76, but we want to round up.
  903.  */
  904. static int topoints(i)
  905. integer i ;
  906. {
  907.    i += 65780L ;
  908.    return (i / 6578176L)*100 + (i % 6578176) * 100 / 6578176 ;
  909. }
  910. /*
  911.  *   Send out the special paper stuff.  If `hed' is non-zero, only
  912.  *   send out lines starting with `!' else send all other lines out.
  913.  */
  914. void paperspec(s, hed)
  915. char *s ;
  916. int hed ;
  917. {
  918.    int sendit ;
  919.  
  920.    while (*s) {
  921.       s++ ;
  922.       if (*s == '\0')
  923.          return ;
  924.       if (*s == '!') {
  925.          s++ ;
  926.          while (*s == ' ') s++ ;
  927.          sendit = hed ;
  928.       } else
  929.          sendit = ! hed ;
  930.       if (sendit) {
  931.          while (*s && *s != '\n')
  932.             (void)putc(*s++, bitfile) ;
  933.          putc('\n', bitfile) ;
  934.       } else {
  935.          while (*s && *s != '\n')
  936.             s++ ;
  937.       }
  938.    }
  939. }
  940. char *epsftest() {
  941.    if (tryepsf && totalpages == 1 && paperfmt == 0 && *iname) {
  942.       findbb() ;
  943.       return nextstring ;
  944.    }
  945.    return 0 ;
  946. }
  947. static char *isepsf = 0 ;
  948. static int endprologsent ;
  949. void
  950. initprinter(n)
  951. int n ; /* number of pages if greater than 0 */
  952. {
  953.    void tell_needed_fonts() ;
  954.  
  955.    n *= pagecopies * collatedcopies ;
  956.    if (*oname != 0) {
  957. /*
  958.  *   We check to see if the first character is a exclamation
  959.  *   point, and popen if so.
  960.  */
  961.       if (*oname == '!' || *oname == '|') {
  962. #ifdef MSDOS
  963.             error("! can't open output pipe") ;
  964. #else
  965. #ifdef VMS
  966.             error("! can't open output pipe") ;
  967. #else
  968. #ifdef VMCMS
  969.             error("! can't open output pipe") ;
  970. #else
  971. #ifdef MVSXA
  972.             error("! can't open output pipe") ;
  973. #else
  974. #ifdef __THINK__
  975.             error("! can't open output pipe") ;
  976. #else
  977. #ifdef OS2
  978.          if (_osmode != OS2_MODE) {
  979.             error("! can't open output pipe") ;
  980.          } else {
  981. #endif
  982.          if (secure || (bitfile=popen(oname+1, "w"))==NULL)
  983.             error("! couldn't open output pipe") ;
  984.          else
  985.             popened = 1 ;
  986. #ifdef OS2
  987.          }
  988. #endif
  989. #endif
  990. #endif
  991. #endif
  992. #endif
  993. #endif
  994.       } else {
  995.          if ((bitfile=fopen(oname,"w"))==NULL)
  996.             error("! couldn't open PostScript file") ;
  997.       }
  998.    } else {
  999.       bitfile = stdout ;
  1000.    }
  1001.    findpapersize() ;
  1002.    if (disablecomments)
  1003.       (void)fprintf(bitfile,
  1004.              "%%!PS (but not EPSF; comments have been disabled)\n") ;
  1005.    else {
  1006.       if (multiplesects)
  1007.          (void)fprintf(bitfile,
  1008.              "%%!PS (but not EPSF because of memory limits)\n") ;
  1009.       else {
  1010.          isepsf = epsftest() ;
  1011.          if (isepsf)
  1012.             (void)fprintf(bitfile, "%%!PS-Adobe-2.0 EPSF-2.0\n") ;
  1013.          else
  1014.             (void)fprintf(bitfile, "%%!PS-Adobe-2.0\n") ;
  1015.       }
  1016.       if (tryepsf && isepsf == 0)
  1017.          error("We tried, but couldn't make it EPSF.") ;
  1018.       (void)fprintf(bitfile, "%%%%Creator: %s", banner + 8) ;
  1019.       if (*iname)
  1020.          (void)fprintf(bitfile, "%%%%Title: %s\n", iname) ;
  1021. #ifdef CREATIONDATE
  1022.       jobtime=time(0);
  1023.       (void)fprintf(bitfile, "%%%%CreationDate: %s",
  1024.                                  asctime(localtime(&jobtime))) ;
  1025. #endif
  1026.       if (! isepsf) {
  1027. /*
  1028.  *   Normally, we wouldn't want to add that second field
  1029.  *   indicating that the page order is reversed, as per page
  1030.  *   644 of the Red book.  But we have to, for many existing
  1031.  *   spoolers.
  1032.  */
  1033.         (void)fprintf(bitfile, "%%%%Pages: %d%s\n", (n ? n : totalpages),
  1034.                                                     (reverse?" -1":"")) ;
  1035.         (void)fprintf(bitfile, "%%%%PageOrder: %sscend\n", reverse?"De":"A");
  1036.       }
  1037.       if (landscape) {
  1038.          fprintf(bitfile, "%%%%Orientation: Landscape\n") ;
  1039.          fprintf(bitfile, "%%%%BoundingBox: 0 0 %d %d\n",
  1040.               topoints(finpapsiz->xsize), topoints(finpapsiz->ysize)) ;
  1041.       } else if (isepsf)
  1042.          fprintf(bitfile, "%%%%BoundingBox: %s\n", isepsf) ;
  1043.       else
  1044.          fprintf(bitfile, "%%%%BoundingBox: 0 0 %d %d\n",
  1045.               topoints(finpapsiz->xsize), topoints(finpapsiz->ysize)) ;
  1046.       tell_needed_fonts() ;
  1047.       paperspec(finpapsiz->specdat, 1) ;
  1048.       (void)fprintf(bitfile, "%%%%EndComments\n") ;
  1049.    }
  1050.    {
  1051.       int i, len ;
  1052.       char *p ;
  1053.  
  1054. /*
  1055.  *   Here, too, we have to be careful not to exceed the line length
  1056.  *   limitation, if possible.
  1057.  */
  1058.       (void)fprintf(bitfile, "%%DVIPSCommandLine:") ;
  1059.       len = 18 ;
  1060.       for (i=0; i<gargc; i++) {
  1061.          p = gargv[i] ;
  1062.          while (*p > ' ')
  1063.             p++ ;
  1064.          if (*p)
  1065.             len += 2 ;
  1066.          len += strlen(gargv[i]) + 1 ;
  1067.          if (len > LINELENGTH) {
  1068.             (void)fprintf(bitfile, "\n%%+") ;
  1069.             len = strlen(gargv[i]) + 3 ;
  1070.             if (*p)
  1071.                len += 2 ;
  1072.          }
  1073.          (void)fprintf(bitfile, (*p ? " \"%s\"" : " %s"), gargv[i]) ;
  1074.       }
  1075.       (void)fprintf(bitfile, "\n%%DVIPSParameters: dpi=%d", actualdpi) ;
  1076.       if (actualdpi != vactualdpi)
  1077.          (void)fprintf(bitfile, "x%d", vactualdpi) ;
  1078.       if (compressed)
  1079.          (void)fprintf(bitfile, ", compressed") ;
  1080.       if (removecomments)
  1081.          (void)fprintf(bitfile, ", comments removed") ;
  1082.       (void)fputc('\n', bitfile) ;
  1083.    }
  1084. #ifdef VMCMS  /* convert preamblecomment to ebcdic so we can read it */
  1085.    {
  1086.       int i ;
  1087.       for ( i=0 ; preamblecomment[i] ; i++ )
  1088.           preamblecomment[i] = ascii2ebcdic[preamblecomment[i]] ;
  1089.    }
  1090. #else
  1091. #ifdef MVSXA   /* IBM: MVS/XA */
  1092.    {
  1093.       int i ;
  1094.       for ( i=0 ; preamblecomment[i] ; i++ )
  1095.           preamblecomment[i] = ascii2ebcdic[preamblecomment[i]] ;
  1096.    }
  1097. #endif  /* VMCMS */
  1098. #endif
  1099.    (void)fprintf(bitfile, "%%DVIPSSource: %s\n", preamblecomment) ;
  1100.    linepos = 0 ;
  1101.    endprologsent = 0 ;
  1102.    if (safetyenclose)
  1103.       (void)fprintf(bitfile, "/SafetyEnclosure save def\n") ;
  1104.    if (! headers_off)
  1105.       send_headers() ;
  1106. }
  1107. void setup() {
  1108.    newline() ;
  1109.    if (endprologsent == 0 && !disablecomments) {
  1110.       (void)fprintf(bitfile, "%%%%EndProlog\n") ;
  1111.       (void)fprintf(bitfile, "%%%%BeginSetup\n") ;
  1112.       if (vactualdpi == actualdpi)
  1113.          (void)fprintf(bitfile, "%%%%Feature: *Resolution %ddpi\n",
  1114.                                            actualdpi) ;
  1115.       else
  1116.          (void)fprintf(bitfile, "%%%%Feature: *Resolution %dx%ddpi\n",
  1117.                                            actualdpi, vactualdpi) ;
  1118.       if (multiplesects && *(finpapsiz->specdat)) {
  1119.          (void)fprintf(bitfile, "TeXDict begin\n") ;
  1120.          paperspec(finpapsiz->specdat, 0) ;
  1121.          (void)fprintf(bitfile, "end\n") ;
  1122.       }
  1123.       if (manualfeed)
  1124.          (void)fprintf(bitfile, "%%%%Feature: *ManualFeed True\n") ;
  1125.       if (multiplesects)
  1126.          (void)fprintf(bitfile, "%%%%EndSetup\n") ;
  1127.    }
  1128.    if (multiplesects && ! disablecomments)
  1129.       (void)fprintf(bitfile, "%%DVIPSBeginSection\n") ;
  1130.    cmdout("TeXDict") ;
  1131.    cmdout("begin") ;
  1132.    if (endprologsent || disablecomments || multiplesects == 0) {
  1133.       (void)fprintf(bitfile, "\n") ;
  1134.       paperspec(finpapsiz->specdat, 0) ;
  1135.    }
  1136.    if (manualfeed) cmdout("@manualfeed") ;
  1137.    if (landscape) cmdout("@landscape") ;
  1138.    if (numcopies != 1) {
  1139.       numout((integer)numcopies) ;
  1140.       cmdout("@copies") ;
  1141.    }
  1142.    if (endprologsent == 0 && !disablecomments) {
  1143.       newline() ;
  1144.       endprologsent = 1 ;
  1145.       if (! multiplesects)
  1146.          (void)fprintf(bitfile, "%%%%EndSetup\n") ;
  1147.    }
  1148. }
  1149. /*
  1150.  *   cleanprinter is the antithesis of the above routine.
  1151.  */
  1152. void
  1153. cleanprinter()
  1154. {
  1155.    (void)fprintf(bitfile, "\n") ;
  1156.    (void)fprintf(bitfile, "userdict /end-hook known{end-hook}if\n") ;
  1157.    if (safetyenclose)
  1158.       (void)fprintf(bitfile, "SafetyEnclosure restore\n") ;
  1159.    if (!disablecomments)
  1160.       (void)fprintf(bitfile, "%%%%EOF\n") ;
  1161.    if (sendcontrolD)
  1162.       (void)putc(4, bitfile) ;
  1163.    if (ferror(bitfile))
  1164.       error("Problems with file writing; probably disk full.") ;
  1165. #ifndef MSDOS
  1166. #ifndef VMS
  1167. #ifndef MVSXA
  1168. #ifndef VMCMS
  1169. #ifndef __THINK__
  1170. #ifdef OS2
  1171.    if (_osmode == OS2_MODE)
  1172. #endif
  1173.       if (popened)
  1174.          (void)pclose(bitfile) ;
  1175. #endif
  1176. #endif
  1177. #endif
  1178. #endif
  1179. #endif
  1180.    if (popened == 0)
  1181.       (void)fclose(bitfile) ;
  1182.    bitfile = NULL ;
  1183. }
  1184.  
  1185. /* this tells dvips that it has no clue where it is. */
  1186. static int thispage = 0 ;
  1187. static integer rulex, ruley ;
  1188. void psflush() {
  1189.    rulex = ruley = rhh = rvv = -314159265 ;
  1190.    lastfont = -1 ;
  1191. }
  1192. /*
  1193.  *   pageinit initializes the output variables.
  1194.  */
  1195. void
  1196. pageinit()
  1197. {
  1198.    psflush() ;
  1199.    newline() ;
  1200.    thispage++ ;
  1201.    if (!disablecomments)
  1202.       if (multiplesects)
  1203. #ifdef SHORTINT
  1204.          (void)fprintf(bitfile, "%%DVIPSSectionPage: %ld\n", pagenum) ;
  1205.       else if (! isepsf)
  1206.          (void)fprintf(bitfile, "%%%%Page: %ld %d\n", pagenum, thispage) ;
  1207. #else
  1208.          (void)fprintf(bitfile, "%%DVIPSSectionPage: %d\n", pagenum) ;
  1209.       else if (! isepsf)
  1210.          (void)fprintf(bitfile, "%%%%Page: %d %d\n", pagenum, thispage) ;
  1211. #endif
  1212.    linepos = 0 ;
  1213.    numout((integer)pagenum) ;
  1214.    numout((integer)thispage-1) ;
  1215.    cmdout("bop") ;
  1216.    d = 0 ;
  1217. }
  1218.  
  1219.  
  1220.  
  1221. /*
  1222.  *   This routine ends a page.
  1223.  */
  1224. void
  1225. pageend()
  1226. {
  1227.    if (instring) {
  1228.       stringend() ;
  1229.       chrcmd('p') ;
  1230.    }
  1231.    cmdout("eop") ;
  1232. }
  1233.  
  1234. /*
  1235.  *   drawrule draws a rule at the specified position.
  1236.  *   It does nothing to save/restore the current position,
  1237.  *   or even draw the current string.  (Rules are normally
  1238.  *   set below the baseline anyway, so this saves us on
  1239.  *   output size almost always.)
  1240.  */
  1241. void
  1242. drawrule(rw, rh)
  1243.         integer rw, rh ;
  1244. {
  1245.    numout((integer)hh) ;
  1246.    numout((integer)vv) ;
  1247.    if (rw == rulex && rh == ruley)
  1248.       chrcmd('V') ;
  1249.    else {
  1250.       numout((integer)rw) ;
  1251.       numout((integer)rh) ;
  1252.       chrcmd('v') ;
  1253.       rulex = rw ;
  1254.       ruley = rh ;
  1255.    }
  1256. }
  1257.  
  1258. /*
  1259.  *   drawchar draws a character at the specified position.
  1260.  */
  1261. void
  1262. drawchar(c, cc)
  1263.         chardesctype *c ;
  1264.         int cc ;
  1265. {
  1266.    hvpos() ;
  1267.    if (lastfont != curfnt->psname) {
  1268.       fontout((int)curfnt->psname) ;
  1269.       lastfont = curfnt->psname ;
  1270.    }
  1271.    scout(cc) ;
  1272.    rhh = hh + c->pixelwidth ; /* rvv = rv */
  1273. }
  1274. /*
  1275.  *   This routine sends out the document fonts comment.
  1276.  */
  1277. void tell_needed_fonts() {
  1278.    struct header_list *hl = ps_fonts_used ;
  1279.    char *q ;
  1280.    int roomleft = -1 ;
  1281.    extern char *get_name() ;
  1282.  
  1283.    if (hl == 0)
  1284.       return ;
  1285.    while (0 != (q=get_name(&hl))) {
  1286.       if ((int)strlen(q) >= roomleft) {
  1287.          if (roomleft != -1) {
  1288.             fprintf(bitfile, "\n%%%%+") ;
  1289.             roomleft = LINELENGTH - 3 ;
  1290.          } else {
  1291.             fprintf(bitfile, "%%%%DocumentFonts:") ;
  1292.             roomleft = LINELENGTH - 16 ;
  1293.          }
  1294.       }
  1295.       fprintf(bitfile, " %s", q) ;
  1296.       roomleft -= strlen(q) + 1 ;
  1297.    }
  1298.    fprintf(bitfile, "\n") ;
  1299. }
  1300.